package edu.wpi.cs509.representation;

import java.io.Serializable;

import edu.wpi.cs509.network.Connection;

/**
 * ClientGame class is a serializable class containing a subset of the primary Game class data
 * to be sent to each player as well as the observers to update the UI.
 * @author Scott Sussman
 *
 */

public class ClientGame extends StrategoObjectBc implements Serializable {
	/**
	 * ClientGame objects are used by the server logic to provide each client with the correct
	 * representation of the current gameboard. The data provided by this object is set based on the
	 * team receiving this data. Therefore the data sent to the RED team or BLUE team will show the
	 * appropriate current piece positions but mask the opposing teams piece types. 
	 */
	private static final long serialVersionUID = 1L;
	private GameID gameID;
	private Gameboard gameboard;
	private TeamColor myColor;
	private String myName;
	private String opponentName;
	private boolean myTurn;
	// controls whether opponent pieces will be hidden
	private boolean obfuscate = true;
	private boolean observer = false;

	/**
	 * ClientGame constructor generates a new object instantiated by the server logic to be passed
	 * to the appropriate team. 
	 * @param name - Object name
	 * @param serverGame - Current game object in play. The current game object contains the complete
	 * board in its current state.
	 * @param myColor - The team color that this ClientGame is being instantiated for
	 * team from viewing the opposing teams piece types.
	 * If mask is set to BOTH this is an observer client game and nothing should be masked.
	 */
	public ClientGame(String name,Game serverGame,TeamColor myColor) {
		super(name);
		
		if (serverGame==null)
			System.out.println("null game");
		
		if (serverGame.gameboard==null)
			System.out.println("null gameboard");
		
		int loop=0;
		
		gameID = serverGame.getGameID();
		gameboard = new Gameboard("client gameboard",true);
		
		this.myColor = myColor;
		Connection me = serverGame.getPlayer(myColor);
		if (me != null) {
			this.myName = me.getUser();
		} else {
			//This means this is an observer and observer is always spectating in red's view, so we are setting red's name here
			this.myName = serverGame.getPlayer(TeamColor.RED).getUser();
		}
		
		Connection opponent = serverGame.getPlayer(TeamColor.getOppositeColor(myColor));
		if (opponent != null) {
			this.opponentName = opponent.getUser();
		} else {
			this.opponentName = null;
		}
		
		this.myTurn = ((serverGame.getWhoseTurn() == myColor) || 
					  (serverGame.getWhoseTurn() == TeamColor.BOTH));
	
		for (loop=0;loop<Gameboard.PIECES;loop++) {
			PlayerPiece redPiece = null;
			PlayerPiece bluePiece = null;
			StrategoPiece redStrategoPiece=null;
			StrategoPiece blueStrategoPiece=null;
			
			// Create a clone of servers player pieces
			try {
				redPiece = (PlayerPiece)serverGame.gameboard.getPlayerPiece(TeamColor.RED,loop).clone(TeamColor.RED);
				bluePiece = (PlayerPiece)serverGame.gameboard.getPlayerPiece(TeamColor.BLUE,loop).clone(TeamColor.BLUE);
			} 
			catch (CloneNotSupportedException cnse) {
				System.out.println("- Caught exception clone not supported");
			}
			
			// create a clone of server stratego pieces and assign them to the cloned player pieces
			try {
				redStrategoPiece = (StrategoPiece)redPiece.pieceType.clone(TeamColor.RED);
				blueStrategoPiece = (StrategoPiece)redPiece.pieceType.clone(TeamColor.BLUE);
			}
			catch (CloneNotSupportedException cnse) {
				System.out.println("- Caught exception clone not supported");
			}
			finally {
				redPiece.pieceType = redStrategoPiece;	
				bluePiece.pieceType = blueStrategoPiece;

				// obuscate opponent pieces
				obfuscate = serverGame.obfuscatePieces();
				if (obfuscate && !isObserverGame()) {
					if (myColor.equals(TeamColor.RED))
						bluePiece.pieceType = StrategoPiece.HIDDEN;
					else if (myColor.equals(TeamColor.BLUE))
						redPiece.pieceType = StrategoPiece.HIDDEN;
				}

				gameboard.setPlayerPiece(redPiece, TeamColor.RED, loop);
				gameboard.setPlayerPiece(bluePiece,TeamColor.BLUE,loop);
			}
		}
	}
	
	/**
	 * getGameboard - This method is used by the client to retrieve the complete gameboard 
	 * with the opponents piece types obfuscated.
	 */
	
	public Gameboard getGameboard() {
		return this.gameboard;
	}

	/**
	 * getGameID - get the gameID object assigned by the server to this object.
	 * @return gameID
	 */
	public GameID getGameID() {
		return this.gameID;
	}
		
	/**
	 * getColor - return the color of this clientGame object
	 * @return clientGameColor
	 */
	public TeamColor getMyColor() {
		return this.myColor;
	}

	/**
	 * Returns the other teams color
	 * @return
	 */
	public TeamColor getOpponentColor() {
		return TeamColor.getOppositeColor(myColor);
	}
	
	/**
	 * Returns my player name in string form, suitable for display
	 */
	public String getMyName() {
		return myName;
	}

	/**
	 * Returns my opponent's name in string form, suitable for display
	 */
	public String getOpponentName() {
		return opponentName;
	}

	/**
	 * returns true if it s currently my turn, false otherwise
	 * @return
	 */
	public boolean isMyTurn() {
		return myTurn;
	}

	/**
	 * Indicates the opponent pieces should be obuscated
	 * @return
	 */
	public boolean obfuscatePieces() {
		return obfuscate;
	}
	
	/**
	 * Indicates the game is an observers
	 * @return
	 */
	public boolean isObserverGame() {
		return observer;
	}
	
	/**
	 * Set this game as an observers game
	 * @return
	 */
	public void setObserverGame(boolean obs) {
		observer = obs;
	}
}
